﻿Imports System.IO.Ports

''' <summary>
''' 串口通讯类
''' </summary>
''' <remarks></remarks>
Public Class COMHelper

    '测试标志
    Private __TestFlag As Boolean = False

    Private _PrintWaitTime As Boolean = False

    Private Const MaxReadTimes As Integer = 3 / 3

    Private Const MaxWriteTimes As Integer = 3 / 3

    Private Const DialTimeout As Integer = 60 '拨号超时时间(秒)

    'todo:超时时间修改为2000毫秒
    '读取数据超时时间(毫秒)
    Private _timeout As Integer = 2500

    Private Shared lockObject As New Object

    Private Shared g_rand As New Random()

    Public Shared ConnectType As Integer

#Region "单例模式"

    Private Shared _instance As COMHelper

    Public Shared ReadOnly Property Instance() As COMHelper
        Get
            If _instance Is Nothing Then
                _instance = New COMHelper
            End If

            Return _instance
        End Get
    End Property

#End Region

#Region "构造函数"

    Public Sub New()
        _sp = New SerialPort()
        '_cs = New ClientSocket()
        'AddHandler _cs.OnDisconnect, OnDisconnect
        'InitSerialPort(1)
    End Sub

#End Region

#Region "成员变量"

    Private _sp As SerialPort

    Private Const MSGLen As Integer = 5

    Private Const WriteTimes As Integer = 3

    Private _cs As ClientSocket

#End Region

#Region "配置方法"

    Private Function GetPort() As Integer
        Return 1
    End Function

    ''' <summary>
    ''' 串口初始化
    ''' </summary>
    ''' <param name="port"></param>
    ''' <remarks></remarks>
    Public Function InitSerialPort(ByVal port As Integer, ByVal p As Parity) As Boolean
        Dim result As Boolean = True

        If _sp.IsOpen Then
            _sp.WriteLine("AT" & ControlChars.NewLine)
            Threading.Thread.Sleep(500)
            Debug.WriteLine("1 ReadExisting()=" & _sp.ReadExisting())
            _sp.Close()
            Threading.Thread.Sleep(200)

        End If

        With _sp
            .PortName = "COM" & port.ToString()
            .BaudRate = 9600

            '.Parity = parity.Even
            'Modem拨号只能采用无校验？（2008-01-21）
            '.Parity = Parity.None  '默认为Parity.None
            .Parity = p

            .DataBits = 8


            '.Handshake = Handshake.RequestToSend
            '.Handshake = Handshake.XOnXOff

            .DtrEnable = True
            .RtsEnable = True

            .ReadBufferSize = 1024
            .WriteBufferSize = 1024

            .ReadTimeout = 3000
            .WriteTimeout = 3000
        End With

        Try
            result = False
            _sp.Open()

            _sp.WriteLine("AT" & ControlChars.NewLine)
            System.Threading.Thread.Sleep(500)

            Debug.WriteLine("2 ReadExisting()=" & _sp.ReadExisting())

            result = True

        Catch ex1 As System.IO.IOException
            Debug.WriteLine("打开串口失败")

        Catch ex As Exception
            Debug.WriteLine("打开串口时发生未知异常")
        End Try

        Return result
    End Function

    ''' <summary>
    ''' Modem初始化
    ''' </summary>
    ''' <param name="port"></param>
    ''' <param name="phone"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function InitModem(ByVal port As Integer, ByVal phone As String) As Boolean
        Try
            If _sp.IsOpen Then
                _sp.WriteLine("AT")
                System.Threading.Thread.Sleep(500)
                _sp.ReadExisting()
            End If
        Catch ex As Exception
            'do noting
        End Try

        '初始化串口
        Dim result As Boolean
        result = InitSerialPort(port, Parity.None)

        Return result AndAlso InitModem(phone)
    End Function

    ''' <summary>
    ''' 初始化Modem
    ''' </summary>
    ''' <param name="phone"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function InitModem(ByVal phone As String) As Boolean
        '拨号
        Dim cmd As String

        'cmd = "ATE0" & ControlChars.NewLine
        '_sp.Write(cmd)

        'System.Threading.Thread.Sleep(200)


        cmd = "ATDT" & phone & "" & ControlChars.NewLine '& ChrW(13)

        Try
            System.Threading.Thread.Sleep(500)
            _sp.ReadExisting()

            _sp.Write(cmd)
        Catch ex As Exception
            Debug.WriteLine("串口写数据失败(发送拨号命令)")
            Throw ex
            Return False
        End Try

        '拨号超时时间（秒）
        Dim waitSecond As Integer = DialTimeout

        Dim str As String = ""

        Dim bConnected As Boolean = False
        For i As Integer = 0 To waitSecond * 10 / 10
            System.Threading.Thread.Sleep(1000)
            Application.DoEvents()


            str &= _sp.ReadExisting()

            If str.IndexOf("CONNECT") >= 0 Then
                bConnected = True
                Exit For
            End If


            If str.IndexOf("BUSY") >= 0 Then
                Throw New Exception("BUSY")
            End If

            If str.IndexOf("ERROR") >= 0 Then
                Debug.WriteLine("拨号发生错误")

                Throw New Exception("ERROR")
            End If

            If str.IndexOf("NO DIALTONE") >= 0 Then
                Throw New Exception("NO DIALTONE")
            End If

        Next
        Return bConnected
    End Function

    Public OnDisconnect As EventHandler(Of TBCC.SocketObject.DisconnectArgs)
#Region "Socket Parameters"
    Private _SocketParameters As New SocketParametersClass()

    Public ReadOnly Property SocketParameters() As SocketParametersClass
        Get
            Return _SocketParameters
        End Get
    End Property
#End Region
    Public Function InitSocket(ByVal ipAddress As String, ByVal port As Integer) As Boolean
        If _cs IsNot Nothing Then
            _cs.ForceClose() : _cs = Nothing
        End If

        _cs = New ClientSocket()
        AddHandler _cs.OnDisconnect, OnDisconnect

        With _cs
            .HeartIdleTime = _SocketParameters.Heartbeat_IdleTime
            .HeartWaitTime = _SocketParameters.Heartbeat_WaitTime
            .HeartRep = _SocketParameters.Heartbeat_Rep
            .ReceiveBufferSize = 1024
            .ReceiveTimeout = 3000
            .SendBufferSize = 1024
            .SendTimeout = 3000
            .HeartDataClient = _cs.Encoding.GetBytes("AT^HEARTBEAT=1" & ControlChars.CrLf)
            .HeartDataServer = _cs.Encoding.GetBytes("AT^HEARTBEAT=OK" & ControlChars.CrLf)
        End With

        If Not _cs.ConnectToServer(ipAddress, port) Then
            If _cs IsNot Nothing Then
                _cs.Close(0)
                _cs = Nothing
            End If
            '_cs.Close(0)

            Return False
        End If

        Return True
    End Function

    Public Sub Close()
        Close(False)
    End Sub
    Public Sub Close(ByVal isForce As Boolean)
        Select Case ConnectType
            Case 0, 1 '拨号,直连
                Try
                    If _sp.IsOpen Then
                        _sp.WriteLine("AT" & ControlChars.NewLine)
                        System.Threading.Thread.Sleep(500)
                        Debug.WriteLine("Before Close: " & _sp.ReadExisting())
                    End If

                Catch ex As Exception
                    Debug.WriteLine(ex.Message)
                End Try


                Try
                    Me._sp.Close()
                Catch ex As Exception
                    Debug.WriteLine(ex.Message)
                End Try
            Case 2 'TCP/IP
                If _cs IsNot Nothing Then
                    If isForce Then
                        _cs.ForceClose()
                    ElseIf Not _cs.IsDisconnected Then
                        _cs.Close(0)
                    End If
                    _cs = Nothing
                End If
        End Select
    End Sub

    ''' <summary>
    ''' 填充本机可用串口到指定的Combobox
    ''' </summary>
    ''' <param name="cbo"></param>
    ''' <remarks></remarks>
    Public Shared Sub FillComName(ByVal cbo As ComboBox)
        For Each comName As String In System.IO.Ports.SerialPort.GetPortNames()
            cbo.Items.Add(comName)
        Next
    End Sub

#End Region

#Region "数据发送方法"

    Public __Timeout As Integer = 0

    Private _max As Long = 0
    Private _min As Long = 2000


    Private _isBusy As Boolean
    Public Property IsBusy() As Boolean
        Get
            Return _isBusy
        End Get
        Set(ByVal value As Boolean)
            _isBusy = value
        End Set
    End Property


    ''' <summary>
    ''' 发送Modbuf命令，并返回接收数据(字节数组类型)
    ''' </summary>
    ''' <param name="outBuf"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function Send(ByVal outBuf() As Byte) As Byte()
        _isBusy = True
        Dim buf() As Byte = Nothing

        If System.Threading.Monitor.TryEnter(lockObject, 2000) Then
            Try
                buf = _LockedSend(outBuf)
            Catch e As Exception
                Debug.Print("serial lock failure: " & e.Message)
                Throw e

            Finally
                System.Threading.Monitor.Exit(lockObject)

            End Try
        End If

        _isBusy = False
        Return buf
    End Function

    Private Function _LockedSend(ByVal outBuf() As Byte) As Byte()
        'Dim wt As New Stopwatch()
#If DEBUG Then
        Static iSend As Integer = 0
        iSend += 1 : Debug.WriteLine(String.Format("第{0}次：", iSend))

        Dim str_outbuf As String = "     "
        For Each bb1 As Byte In outBuf
            str_outbuf += " " & bb1.ToString()
        Next
        Debug.WriteLine(str_outbuf)
#End If

        'wt.Start()
        Try
            'Dim bb(15) As Byte
            'For ii As Integer = 0 To 15
            '    If ii < outBuf.Length Then
            '        bb(ii) = outBuf(ii)
            '    Else
            '        bb(ii) = 0
            '    End If
            'Next
            '_sp.Write(bb, 0, bb.Length)
            Select Case ConnectType
                Case 0, 1 '拨号,直连
                    _sp.ReadExisting()
                    _sp.Write(outBuf, 0, outBuf.Length)
                Case 2 'TCP/IP
  
                    _cs.ReceiveExisting()
                    _cs.Send(outBuf, 0, outBuf.Length)
            End Select
        Catch ex As Exception
            log(ex, "")

#If DEBUG Then
            Throw ex
#End If
            Return Nothing
        End Try

        Dim inBuf(1024) As Byte

        'Sleep(150)
        If Wait4ReadBufffer(3) = False Then
            __Timeout += 1
            Debug.WriteLine("Timeout3:" & __Timeout.ToString())
            'MsgBox("3333")
            Return Nothing
        End If

        Try
            Sleep(1)
            Select Case ConnectType
                Case 0, 1 '拨号,直连
                    _sp.Read(inBuf, 0, 3)
                Case 2 'TCP/IP
                    _cs.Receive(inBuf, 0, 3)
            End Select

            If _PrintWaitTime Then
                Debug.Write(String.Format("前三个字节： {0}  {1}  {2}", inBuf(0), inBuf(1), inBuf(2)))
            End If
        Catch ex As Exception
            __Timeout += 1
            Debug.WriteLine("串口接收数据超时(3byte)Timeout:" & __Timeout.ToString())

            Return Nothing
        End Try

        '增加历史数据读取41请求 43返回
        If outBuf(1) = FunctionCode.HistoryByteRead AndAlso inBuf(1) = FunctionCode.HistoryByteReadReturn Then

            Dim inBuf1(1024) As Byte
            Array.Copy(inBuf, inBuf1, 3)

            If Wait4ReadBufffer(4) = False Then
                __Timeout += 1
                Debug.WriteLine("Timeout7:" & __Timeout.ToString())
                'MsgBox("3333")
                Return Nothing
            End If
            Try
                Sleep(1)
                Select Case ConnectType
                    Case 0, 1 '拨号,直连
                        _sp.Read(inBuf1, 3, 4)
                    Case 2 'TCP/IP
                        _cs.Receive(inBuf1, 3, 4)
                End Select
            Catch ex As Exception
                __Timeout += 1
                Debug.WriteLine("串口接收数据超时(7byte)Timeout:" & __Timeout.ToString())

                Return Nothing
            End Try


            If outBuf(0) <> inBuf1(0) Then

                __Timeout += 1
                Debug.WriteLine(String.Format("但是网络地址错误 {0}<>{1} Timeout:" & __Timeout.ToString(), outBuf(0), inBuf(0)))
                Return Nothing

            End If

            If outBuf(2) <> inBuf1(2) Then
                __Timeout += 1
                Debug.WriteLine(String.Format("待访问起始页地址的高位字节{0}<>{1}错误" & __Timeout.ToString(), outBuf(0), inBuf(0)))
                Return Nothing

            End If


            If outBuf(3) <> inBuf1(3) Then
                __Timeout += 1
                Debug.WriteLine(String.Format("待访问起始页地址的低位字节{0}<>{1}错误" & __Timeout.ToString(), outBuf(0), inBuf(0)))
                Return Nothing

            End If

            If outBuf(4) <> inBuf1(4) Then
                __Timeout += 1
                Debug.WriteLine(String.Format("待访问起始页地址的上下半页类型字节{0}<>{1}错误" & __Timeout.ToString(), outBuf(0), inBuf(0)))
                Return Nothing

            End If

            If outBuf(5) <> inBuf1(5) Then
                __Timeout += 1
                Debug.WriteLine(String.Format("待访问起始页地址的上下半页类型1字节{0}<>{1}错误" & __Timeout.ToString(), outBuf(0), inBuf(0)))
                Return Nothing

            End If

            'If outBuf(6) <> inBuf1(6) Then
            '    __Timeout += 1
            '    Debug.WriteLine(String.Format("待访问起始页地址的高位字节{0}<>{1}错误" & __Timeout.ToString(), outBuf(0), inBuf(0)))
            '    Return Nothing

            'End If

            Dim len1 As Integer
            len1 = inBuf1(6)      '数据长度(字节) + 6字节的CRC


            If Wait4ReadBufffer(len1 + 2) = False Then

                __Timeout += 1

                Return Nothing
            End If

            Try
                Select Case ConnectType
                    Case 0, 1 '拨号,直连
                        _sp.Read(inBuf1, 7, len1 + 2)
                    Case 2 'TCP/IP
                        _cs.Receive(inBuf1, 7, len1 + 2)
                End Select
            Catch ex As Exception
                Debug.WriteLine(String.Format("串口接收数据超时(={0}byte)", len1 + 2))
                Return Nothing

            End Try

            '定义数据数组,数组长度为： 网络地址位(1字节)+功能码(1字节)+数据长度位(1字节)+实际数据长度(len字节)
            Dim dLen1 As Integer = 7 + len1
            Dim DataBuf1(dLen1 - 1) As Byte

            '计算接收数据的CRC
            Array.Copy(inBuf1, DataBuf1, dLen1)
            Dim b1(1) As Byte
            b1 = CRC.CRC16(DataBuf1)

            '验证CRC
            If b1(0) <> inBuf1(dLen1) OrElse b1(1) <> inBuf1(dLen1 + 1) Then

                __Timeout += 1
                Debug.WriteLine("CRC错误Timeout:" & __Timeout.ToString())
                Return Nothing
            End If

            Dim realDataBuf1(len1 - 1) As Byte

            For i As Integer = 7 To DataBuf1.Length - 1
                realDataBuf1(i - 7) = DataBuf1(i)
            Next

            Me.Sleep(100)

            Return realDataBuf1



        End If



        If outBuf(0) <> inBuf(0) Then

            __Timeout += 1
            Debug.WriteLine(String.Format("但是网络地址错误 {0}<>{1} Timeout:" & __Timeout.ToString(), outBuf(0), inBuf(0)))
            Return Nothing

        End If

        If outBuf(1) <> inBuf(1) Then
            'If outBuf(1) = FunctionCode.HistoryByteRead Then
            '    If outBuf(4) = (1 And &HFF00) >> 8 AndAlso FunctionCode.HistoryByteRead1 <> inBuf(1) Then  '增加返回上半页验证
            '        __Timeout += 1
            '        Debug.WriteLine("上半页但是功能码错误Timeout:" & __Timeout.ToString())
            '        Return Nothing

            '    ElseIf outBuf(4) = (2 And &HFF00) >> 8 AndAlso FunctionCode.HistoryByteRead2 <> inBuf(1) Then  '增加返回下半页验证
            '        __Timeout += 1
            '        Debug.WriteLine("下半页但是功能码错误Timeout:" & __Timeout.ToString())
            '        Return Nothing
            '    End If
            'Else

            __Timeout += 1
            Debug.WriteLine("但是功能码错误Timeout:" & __Timeout.ToString())
            Return Nothing
            ' End If

        End If


        Dim len As Integer
        len = inBuf(2)      '数据长度(字节) + 2字节的CRC


        If Wait4ReadBufffer(len + 2) = False Then

            __Timeout += 1

            Return Nothing
        End If

        'wt.Stop()
        'If wt.ElapsedMilliseconds > _max Then
        '    _max = wt.ElapsedMilliseconds
        'End If
        'If wt.ElapsedMilliseconds < _min Then
        '    _min = wt.ElapsedMilliseconds
        'End If
        'Debug.WriteLine("ReadExisting's Time=" & wt.ElapsedMilliseconds & String.Format("  min={0} max={1}", _min, _max))

        Try
            Select Case ConnectType
                Case 0, 1 '拨号,直连
                    _sp.Read(inBuf, 3, len + 2)
                Case 2 'TCP/IP
                    _cs.Receive(inBuf, 3, len + 2)
            End Select
        Catch ex As Exception
            Debug.WriteLine(String.Format("串口接收数据超时(={0}byte)", len + 2))
            Return Nothing

        End Try


        '定义数据数组,数组长度为： 网络地址位(1字节)+功能码(1字节)+数据长度位(1字节)+实际数据长度(len字节)
        Dim dLen As Integer = 3 + len
        Dim DataBuf(dLen - 1) As Byte

        '计算接收数据的CRC
        Array.Copy(inBuf, DataBuf, dLen)
        Dim b(1) As Byte
        b = CRC.CRC16(DataBuf)

        '验证CRC
        If b(0) <> inBuf(dLen) OrElse b(1) <> inBuf(dLen + 1) Then

            __Timeout += 1
            Debug.WriteLine("CRC错误Timeout:" & __Timeout.ToString())
            Return Nothing
        End If

        Dim realDataBuf(len - 1) As Byte

        For i As Integer = 3 To DataBuf.Length - 1
            realDataBuf(i - 3) = DataBuf(i)
        Next

        Me.Sleep(100)

        Return realDataBuf
    End Function

    ''' <summary>
    ''' 读字节数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Byte()
        '消息字节数组
        Dim msgBuf(MSGLen) As Byte
        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = functionCode                '功能码
        msgBuf(2) = (offset And &HFF00) >> 8    '待访问起始地址的高位字节
        msgBuf(3) = offset And &HFF             '待访问起始地址的低位字节
        msgBuf(4) = (count And &HFF00) >> 8     '待访问地址数量的高位字节
        msgBuf(5) = count And &HFF              '待访问地址数量的高位字节

        '输出数字
        Dim outBuf(MSGLen + 2) As Byte

        msgBuf.CopyTo(outBuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)

        'Dim str As String = String.Format("校验码：{0:X}-{1:X}", b(0), b(1))
        'Debug.WriteLine(str)

        outBuf(MSGLen + 1) = b(0)               'CRC高位
        outBuf(MSGLen + 2) = b(1)               'CRC低位

#If DEBUG Then
        For t As Integer = 0 To outBuf.Length - 1
            'Debug.WriteLine(String.Format("outBuf({0})={1:X}", t, outBuf(t)))
        Next
#End If

        Try
            Return Send(outBuf)
        Catch ex As Exception
            Throw ex
        End Try

    End Function

    Private Shared ss As Integer = 0

    ''' <summary>
    ''' 读取Float数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4Single(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Single()
        If __TestFlag Then
            Randomize()
            Dim r As New Random()
            Dim __temp(count - 1) As Single
            For i As Integer = 0 To __temp.Length - 1
                __temp(i) = r.Next(1, 1000) ' (200 - r.Next(1, 400)).ToString() '& "." & Now.Second & Now.Millisecond.ToString()
                ss += 20
                __temp(i) = ss Mod r.Next(300, 1000)   'r.Next(1, 1000) & "." & ss
                '__temp(i) = i & "." & i.ToString()
            Next
            Return __temp
        End If

        Dim buf() As Byte
        'buf = Send(NetAddress, functionCode, offset, count)
        buf = Send4Byte(NetAddress, functionCode, offset, count)

        If buf Is Nothing Then
            Return Nothing
        End If

        Dim len As Integer
        len = buf.Length / 4

        Dim SingleBuf(len - 1) As Single
        For i As Integer = 0 To SingleBuf.GetUpperBound(0)
            'SingleBuf(i) = (buf(i * 4) And &HFFFF) << 8 + (buf(i * 4 + 1) And &HFFFF) + (buf(i * 4 + 2) And &HFFFF) << 24 + (buf(i * 4 + 3) And &HFFFF) << 16
            SingleBuf(i) = NumericConvert.Byte2Single(buf, i)
        Next

        Return SingleBuf
    End Function

    ''' <summary>
    ''' 读取Float数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function _Send4Single(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Single()
        Dim buf() As Byte
        buf = Send(NetAddress, functionCode, offset, count)

        If buf Is Nothing Then
            Return Nothing
        End If

        Dim len As Integer
        len = buf.Length / 4

        Dim SingleBuf(len - 1) As Single
        For i As Integer = 0 To SingleBuf.GetUpperBound(0)
            'SingleBuf(i) = (buf(i * 4) And &HFFFF) << 8 + (buf(i * 4 + 1) And &HFFFF) + (buf(i * 4 + 2) And &HFFFF) << 24 + (buf(i * 4 + 3) And &HFFFF) << 16
            SingleBuf(i) = NumericConvert.Byte2Single(buf, i)
        Next

        Return SingleBuf
    End Function

    ''' <summary>
    ''' 读取Int数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4Short(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Short()
        If __TestFlag Then
            Dim __temp(count - 1) As Short
            For i As Integer = 0 To __temp.Length - 1
                '__temp(i) = i * 100 + Now.Second
                __temp(i) = g_rand.Next(1, 250)
            Next
            Return __temp
        End If

        Dim buf() As Byte
        'buf = Send(NetAddress, functionCode, offset, count)
        buf = Send4Byte(NetAddress, functionCode, offset, count)

        If buf Is Nothing Then
            Return Nothing
        End If

        Dim len As Integer
        len = buf.Length / 2

        Dim shortBuf(len - 1) As Short
        For i As Integer = 0 To shortBuf.GetUpperBound(0)
            'shortBuf(i) = (buf(i * 2) And &HFFFF) << 8 + buf(i * 2 + 1)
            Try
                '    If buf(i * 2) * 256 + buf(i * 2 + 1) <> &HFF Then
                '        'todo:有符号的Short的转换？
                '        shortBuf(i) = NumericConvert.Byte2Short(buf(i * 2), buf(i * 2 + 1))
                '    End If
                shortBuf(i) = NumericConvert.Byte2Short(buf(i * 2), buf(i * 2 + 1))

            Catch ex As Exception
                Debug.Write("Send4Short(): Byte到Short的转换错误")

                shortBuf(i) = 0
            End Try

        Next

        Return shortBuf
    End Function





    ''' <summary>
    ''' 读取Int数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4UShort(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As UShort()
        If __TestFlag Then
            Dim __temp(count - 1) As UShort
            For i As Integer = 0 To __temp.Length - 1
                '__temp(i) = i * 100 + Now.Second
                __temp(i) = g_rand.Next(1, 250)
            Next
            Return __temp
        End If

        Dim buf() As Byte
        'buf = Send(NetAddress, functionCode, offset, count)
        buf = Send4Byte(NetAddress, functionCode, offset, count)

        If buf Is Nothing Then
            Return Nothing
        End If

        Dim len As Integer
        len = buf.Length / 2

        Dim shortBuf(len - 1) As UShort
        For i As Integer = 0 To shortBuf.GetUpperBound(0)
            'shortBuf(i) = (buf(i * 2) And &HFFFF) << 8 + buf(i * 2 + 1)
            Try
                'If buf(i * 2) * 256 + buf(i * 2 + 1) <> &HFF Then
                '    'todo:有符号的Short的转换？
                '    shortBuf(i) = buf(i * 2) * 256 + buf(i * 2 + 1) Mod Short.MaxValue
                'End If

                shortBuf(i) = buf(i * 2) * 256 + buf(i * 2 + 1) Mod Short.MaxValue

            Catch ex As Exception
                Debug.Write("Send4Short(): Byte到Short的转换错误")
                shortBuf(i) = 0
            End Try

        Next

        Return shortBuf
    End Function

    ''' <summary>
    ''' 读取字节数组
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4Byte(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Byte()
        '-----------------------------------------------
        '测试用代码
        If __TestFlag Then
            Dim __temp(count - 1) As Byte

            Randomize()
            Dim r As New Random
            If r.Next(1, 10) = 1 Then
                __temp(0) = r.Next(10)
            End If
            For i As Integer = 0 To __temp.Length - 1
                __temp(i) = r.Next(1, 100)
            Next
            Return __temp
        End If
        '-----------------------------------------------

        Dim buf() As Byte = Nothing
        Try
            For i As Integer = 1 To 1 ' MaxReadTimes
                buf = Send(NetAddress, functionCode, offset, count)
                If buf IsNot Nothing Then
                    Exit For
                End If
                'MsgBox(i)
                Debug.WriteLine(i & "Error")
                'Sleep(100)
            Next

        Catch ex As Exception

            Throw ex
        End Try


        Return buf
    End Function

    ''' <summary>
    ''' 读取字节数组(按word读取,然后将每个word解析程2个Byte)
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4Byte1(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Byte()
        '-----------------------------------------------
        '测试用代码
        If __TestFlag Then
            Dim __temp(count - 1) As Byte

            Randomize()
            Dim r As New Random
            If r.Next(1, 10) = 1 Then
                __temp(0) = r.Next(10)
            End If
            For i As Integer = 0 To __temp.Length - 1
                __temp(i) = r.Next(1, 100)
            Next
            Return __temp
        End If
        '-----------------------------------------------

        Dim buf(count - 1) As Byte
        Dim bufS() As Short
        bufS = Send4Short(NetAddress, functionCode, offset, count / 2)

        If bufS Is Nothing Then
            Return Nothing
        End If

        For i As Integer = 0 To bufS.Length - 1
            buf(2 * i + 0) = bufS(i) Mod 256
            buf(2 * i + 1) = bufS(i) \ 256
        Next

        Return buf
    End Function


    ''' <summary>
    ''' 读取字节数组(按word读取,然后将每个word的低字节解析成结果,高字节丢弃)
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="count"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function Send4Byte2(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal count As UShort) As Byte()
        '-----------------------------------------------
        '测试用代码
        If __TestFlag Then
            Dim __temp(count - 1) As Byte

            Randomize()
            Dim r As New Random
            If r.Next(1, 10) = 1 Then
                __temp(0) = r.Next(10)
            End If
            For i As Integer = 0 To __temp.Length - 1
                __temp(i) = r.Next(1, 100)
            Next
            Return __temp
        End If
        '-----------------------------------------------

        Dim buf(count - 1) As Byte
        Dim bufS() As Short
        bufS = Send4Short(NetAddress, functionCode, offset, count)

        If bufS Is Nothing Then
            Return Nothing
        End If

        For i As Integer = 0 To bufS.Length - 1
            buf(i) = bufS(i) Mod 256
        Next

        Return buf
    End Function


    ''' <summary>
    ''' 写数据(如果写失败,则连续写MaxWriteTimes次,直到写成功或者连续写入失败次数超过MaxWriteTimes次)
    ''' </summary>
    ''' <param name="outBuf"></param>
    ''' <returns>写成功返回True,否则返回False</returns>
    ''' <remarks></remarks>
    Private Overloads Function Write(ByVal outBuf() As Byte) As Boolean
        Dim result As Boolean
        Dim iTry As Integer = 1

        result = _Write(outBuf)

        While result = False AndAlso iTry < MaxWriteTimes
            result = _Write(outBuf)
            iTry += 1
        End While

        Return result

    End Function

    Private _isWrite As Boolean = False

    ''' <summary>
    ''' 写数据(同步）
    ''' </summary>
    ''' <param name="outBuf"></param>
    ''' <returns>写成功返回True,否则返回False</returns>
    ''' <remarks></remarks>
    Private Overloads Function _Write(ByVal outBuf() As Byte) As Boolean
        Dim result As Boolean

        _isBusy = True
        SyncLock lockObject
            result = _LockedWrite(outBuf)
        End SyncLock
        _isBusy = False

        Return result
    End Function

    ''' <summary>
    ''' 写数据
    ''' </summary>
    ''' <param name="OutBuf"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function _LockedWrite(ByVal OutBuf() As Byte) As Boolean
        If __TestFlag Then
            Dim str As String = ""
            For i As Integer = 0 To OutBuf.Length - 1
                str &= " " & String.Format("{0:X}", OutBuf(i))
            Next
            Debug.WriteLine(str)

            Return True
        End If

        PrintBuffer(OutBuf, "_Write() ")

        Select Case ConnectType
            Case 0, 1
                _sp.ReadExisting()

                _sp.Write(OutBuf, 0, OutBuf.Length)
            Case 2
                _cs.ReceiveExisting()
                _cs.Send(OutBuf, 0, OutBuf.Length)
        End Select

        'System.Threading.Thread.Sleep(1000)

        If Me.Wait4ReadBufffer(OutBuf.Length) = False Then
            Return False
        End If

        Dim inBuf(OutBuf.Length - 1) As Byte
        Select Case ConnectType
            Case 0, 1
                _sp.Read(inBuf, 0, OutBuf.Length)
            Case 2
                _cs.Receive(inBuf, 0, OutBuf.Length)
        End Select

        Dim bDiff As Boolean = False

        For i As Integer = 0 To OutBuf.Length - 1
            If inBuf(i) <> OutBuf(i) Then
                bDiff = True
                Exit For
            End If
        Next

        Return Not bDiff
    End Function

    ''' <summary>
    ''' 准备输出数据
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="functionCode"></param>
    ''' <param name="offset"></param>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function PrepareBuffer(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Short) As Byte()
        '消息字节数组
        Dim msgBuf(MSGLen) As Byte
        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = functionCode                '功能码
        msgBuf(2) = (offset And &HFF00) >> 8    '待访问起始地址的高位字节
        msgBuf(3) = offset And &HFF             '待访问起始地址的低位字节
        msgBuf(4) = (value And &HFF00) >> 8     '待访问地址数量的高位字节
        msgBuf(5) = value And &HFF              '待访问地址数量的高位字节

        '输出数字
        Dim outBuf(MSGLen + 2) As Byte

        msgBuf.CopyTo(outBuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)
        outBuf(MSGLen + 1) = b(0)               'CRC高位
        outBuf(MSGLen + 2) = b(1)               'CRC低位

        Return outBuf
    End Function

    Private Function PrepareBuffer(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Byte()) As Byte()
        '消息字节数组
        Dim msgBuf(MSGLen) As Byte
        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = functionCode                '功能码
        msgBuf(2) = (offset And &HFF00) >> 8    '待访问起始地址的高位字节
        msgBuf(3) = offset And &HFF             '待访问起始地址的低位字节
        msgBuf(4) = value(0)                    '待访问地址数量的高位字节
        msgBuf(5) = value(1)                    '待访问地址数量的高位字节

        '输出数字
        Dim outBuf(MSGLen + 2) As Byte

        msgBuf.CopyTo(outBuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)
        outBuf(MSGLen + 1) = b(0)               'CRC高位
        outBuf(MSGLen + 2) = b(1)               'CRC低位

        Return outBuf
    End Function


    Private Function PrepareBuffer(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal data As Byte()) As Byte()
        Dim msgLen As Integer = data.Length

        Dim msgBuf(msgLen) As Byte
        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = functionCode                '功能码

        '数据
        For i As Integer = 0 To data.Length - 1
            msgBuf(2 + i) = data(i)
        Next

        '输出字节数组
        Dim outBuf(msgLen + 2) As Byte

        msgBuf.CopyTo(outBuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)
        outBuf(msgLen + 1) = b(0)               'CRC高位
        outBuf(msgLen + 2) = b(1)               'CRC低位

        Return outBuf
    End Function



    ''' <summary>
    ''' 写Byte数据
    ''' </summary>
    ''' <param name="NetAddress">网络地址</param>
    ''' <param name="functionCode">功能代码</param>
    ''' <param name="offset">地址码</param>
    ''' <param name="value">待写值</param>
    ''' <returns>True表示写操作成功，False表示写操作失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Write(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Byte) As Boolean
        Dim shortValue As Short
        shortValue = value
        Return Write(NetAddress, functionCode, offset, shortValue)
    End Function

    ''' <summary>
    ''' 写Short数据
    ''' </summary>
    ''' <param name="NetAddress">网络地址</param>
    ''' <param name="functionCode">功能代码</param>
    ''' <param name="offset">地址码</param>
    ''' <param name="value">待写值</param>
    ''' <returns>True表示写操作成功，False表示写操作失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Write(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Short) As Boolean
        Dim vb() As Byte
        vb = BitConverter.GetBytes(value)

        Dim t(1) As Byte
        t(0) = vb(1)
        t(1) = vb(0)

        Dim outBuf() As Byte
        'outBuf = PrepareBuffer(NetAddress, functionCode, offset, value)
        outBuf = PrepareBuffer(NetAddress, functionCode, offset, t)

        Dim result As Boolean
        result = Write(outBuf)
        Return result
    End Function


    ''' <summary>
    ''' 写Short数据
    ''' </summary>
    ''' <param name="NetAddress">网络地址</param>
    ''' <param name="functionCode">功能代码</param>
    ''' <param name="offset">地址码</param>
    ''' <param name="value">待写值</param>
    ''' <returns>True表示写操作成功，False表示写操作失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Write(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As UShort) As Boolean
        Dim vb() As Byte
        vb = BitConverter.GetBytes(value)

        Dim t(1) As Byte
        t(0) = value \ 256
        t(1) = value Mod 256

        Dim outBuf() As Byte
        'outBuf = PrepareBuffer(NetAddress, functionCode, offset, value)
        outBuf = PrepareBuffer(NetAddress, functionCode, offset, t)

        Dim result As Boolean
        result = Write(outBuf)
        Return result
    End Function

    ''' <summary>
    ''' 写Single数据
    ''' </summary>
    ''' <param name="NetAddress">网络地址</param>
    ''' <param name="functionCode">功能代码</param>
    ''' <param name="offset">地址码</param>
    ''' <param name="value">待写值</param>
    ''' <returns>True表示写操作成功，False表示写操作失败</returns>
    ''' <remarks></remarks>
    Public Overloads Function Write(ByVal NetAddress As Byte, ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Single) As Boolean
        Dim vb() As Byte
        vb = NumericConvert.Single2Byte(value)

        'Dim sLow, sHigh As Short
        'sHigh = (value And &HFFFF0000) >> 16
        'sLow = value And &HFFFF

        Dim bLow(1) As Byte
        bLow(0) = vb(1)
        bLow(1) = vb(0)

        Dim bHigh(1) As Byte
        bHigh(0) = vb(3)
        bHigh(1) = vb(2)

        Dim bResult As Boolean

        Dim outBuf() As Byte

        '发送Float值的低位Int
        outBuf = PrepareBuffer(NetAddress, functionCode, offset, bLow)
        bResult = Write(outBuf)

        If bResult = False Then
            Debug.WriteLine("发送Float值的低位Int失败")
            Return False
        End If

        '发送Float值的高位Int
        outBuf = PrepareBuffer(NetAddress, functionCode, offset + 1, bHigh)
        Sleep(4)
        Return bResult And Write(outBuf)
    End Function

    ''' <summary>
    ''' 写int
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="offset"></param>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overloads Function Write(ByVal NetAddress As Byte, ByVal offset As UShort, ByVal value As Short) As Boolean
        Stop
        Return False
    End Function


    ''' <summary>
    ''' 写Single
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="offset"></param>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overloads Function WriteSingle(ByVal NetAddress As Byte, ByVal offset As UShort, ByVal value As Single) As Boolean
        Dim vb() As Byte
        vb = NumericConvert.Single2Byte(value)

        If vb Is Nothing OrElse vb.Length <> 4 Then
            '浮点数转换错误
            Return False
        End If

        Dim msgBuf(10) As Byte
        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = &H10                        '功能码16
        msgBuf(2) = (offset And &HFF00) >> 8    '地址
        msgBuf(3) = offset And &HFF             '
        msgBuf(4) = 0                           '数量
        msgBuf(5) = 2
        msgBuf(6) = 4                           '字节数
        msgBuf(7) = vb(1)                       '数据
        msgBuf(8) = vb(0)                       '数据
        msgBuf(9) = vb(3)                       '数据
        msgBuf(10) = vb(2)                      '数据

        '输出数字
        Dim outBuf(12) As Byte

        msgBuf.CopyTo(outBuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)
        outBuf(11) = b(0)               'CRC高位
        outBuf(12) = b(1)               'CRC低位

        Dim bResult As Boolean

        bResult = WriteSingle(outBuf)

        Return bResult

    End Function

    ''' <summary>
    ''' 写单个浮点数(通过16功能码一次写)
    ''' </summary>
    ''' <param name="buf"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Overloads Shared Function WriteSingle(ByVal buf() As Byte) As Boolean

        Return True
    End Function

    ''' <summary>
    ''' 一次写整个浮点数(多字写)
    ''' </summary>
    ''' <param name="NetAddress"></param>
    ''' <param name="offset"></param>
    ''' <param name="value"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overloads Function _Write(ByVal NetAddress As Byte, ByVal offset As UShort, ByVal value As Single) As Boolean
        Dim FunctionCode As Byte = 16

        '将单个浮点数表示成字节数组
        Dim vBuf() As Byte
        vBuf = NumericConvert.Single2Byte(value)

        Dim bResult As Boolean

        '消息长度（不包括CRC)
        Dim msgLen As Byte = 11

        '定义消息字节数组
        Dim msgBuf(msgLen - 1) As Byte

        msgBuf(0) = NetAddress                  '网络地址
        msgBuf(1) = 16                          '功能码
        msgBuf(2) = (offset And &HFF00) >> 8    '待访问起始地址的高位字节
        msgBuf(3) = offset And &HFF             '待访问起始地址的低位字节

        msgBuf(4) = 0                           '字数高字节
        msgBuf(5) = 2                           '字数低字节

        msgBuf(6) = 4                           '数据长度(字节数)

        msgBuf(7) = vBuf(1)                     'msgBuf(7)-msgBuf(10)为浮点数的字节流,顺序为1、0、3、2
        msgBuf(8) = vBuf(0)
        msgBuf(9) = vBuf(3)
        msgBuf(10) = vBuf(2)

        '定义输出缓冲区（包括CRC)
        Dim outbuf(msgLen + 2) As Byte

        msgBuf.CopyTo(outbuf, 0)

        '增加CRC
        Dim b(1) As Byte
        b = CRC.CRC16(msgBuf)
        outbuf(msgLen + 0) = b(0)               'CRC高位
        outbuf(msgLen + 1) = b(1)               'CRC低位

        '发送Float值 
        bResult = Write(outbuf)

        If bResult = False Then
            Debug.WriteLine("写Float值失败")
        End If

        Return bResult
    End Function


#End Region

    ''' <summary>
    ''' 暂停n毫秒
    ''' </summary>
    ''' <param name="n"></param>
    ''' <remarks></remarks>
    Private Sub Sleep(ByVal n As Integer)
        Dim delta As Integer = 50
        Dim index As Integer = 0
        While index <= n
            index += delta
            System.Threading.Thread.Sleep(delta)
            Application.DoEvents()
        End While
    End Sub



    Public Property timeout() As Integer
        Get
            Return _timeout
        End Get
        Set(ByVal value As Integer)
            _timeout = value
        End Set
    End Property


    ''' <summary>
    ''' 等待串口接收缓冲区中的数据的字节数超过指定的n个字节(包括n个字节)
    ''' </summary>
    ''' <param name="n"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Function Wait4ReadBufffer(ByVal n As Integer) As Boolean
        Dim et As Integer = 0
        Dim testBuf(1024) As Byte

        Select Case ConnectType
            Case 0, 1 '直连,拨号

                While _sp.BytesToRead < n

                    If Me._PrintWaitTime Then
                        Debug.WriteLine(String.Format("_sp.BytesToRead({0}) < n({1}) et={2}", _sp.BytesToRead, n, et))
                    End If

                    ' _sp.Read(testBuf, 0, _sp.BytesToRead)

                    Sleep(1)   '睡眠1实际等待10秒
                    et += 12
                    If et > _timeout Then
                        _sp.Read(testBuf, 0, _sp.BytesToRead)
                        Debug.WriteLine("接收数据超时n=" & n, Nothing)


                        If Me._PrintWaitTime Then
                            Dim bbb(255) As Byte
                            Dim ilen2 As Integer = _sp.BytesToRead
                            _sp.Read(bbb, 0, _sp.BytesToRead)

                            Dim ss As String = "部分数据："
                            For iss As Integer = 0 To ilen2 - 1
                                ss &= " " & bbb(iss)
                            Next
                            Debug.WriteLine(ss)
                            Debug.WriteLine("Return False")
                        End If

                        Return False
                    End If
                End While

            Case 2 'TCP/IP

                While _cs.Available < n
                    If Me._PrintWaitTime Then
                        Debug.WriteLine(String.Format("_cs.Available({0}) < n({1}) et={2}", _cs.Available, n, et))
                    End If

                    Sleep(1)
                    et += 12
                    If et > _timeout Then
                        Debug.WriteLine("接收数据超时n=" & n & ", _cs.Available=" & _cs.Available, Nothing)

                        If Me._PrintWaitTime Then
                            Dim bbb(255) As Byte
                            Dim ilen2 As Integer = _cs.Available
                            _cs.Receive(bbb, 0, _cs.Available)

                            Dim ss As String = "部分数据："
                            For iss As Integer = 0 To ilen2 - 1
                                ss &= " " & bbb(iss)
                            Next
                            Debug.WriteLine(ss)
                            Debug.WriteLine("Return False")
                        End If

                        Return False
                    End If
                End While

        End Select


        If _PrintWaitTime Then
            Select Case ConnectType
                Case 0, 1
                    Debug.WriteLine(String.Format("_sp.BytesToRead({0}) < n({1}) et={2}", _sp.BytesToRead, n, et))
                Case 2
                    Debug.WriteLine(String.Format("_cs.Available({0}) < n({1}) et={2}", _cs.Available, n, et))
            End Select
        End If


        If n <> 3 AndAlso Me._PrintWaitTime Then
            Debug.WriteLine("Return True" & n)
        End If


        Return True
    End Function

    ''' <summary>
    ''' 保存日志
    ''' </summary>
    ''' <param name="ex"></param>
    ''' <param name="msg"></param>
    ''' <remarks></remarks>
    Private Sub log(ByVal ex As Exception, ByVal msg As String)
        Debug.WriteLine("串口发送数据失败")
    End Sub


    ''' <summary>
    ''' 发送广播消息
    ''' </summary>
    ''' <param name="functionCode">功能码</param>
    ''' <param name="offset">地址</param>
    ''' <param name="value">数据</param>
    ''' <remarks></remarks>
    Public Sub Broadcast(ByVal functionCode As Byte, ByVal offset As UShort, ByVal value As Short)
        Dim outBuf() As Byte
        outBuf = Me.PrepareBuffer(0, functionCode, offset, value)

        Select Case ConnectType
            Case 0, 1 '拨号,直连
                _sp.ReadExisting()

                Sleep(500)
                _sp.Write(outBuf, 0, outBuf.Length)
                Sleep(500)
            Case 2 'TCP/IP
                _cs.ReceiveExisting()

                Sleep(500)
                _cs.Send(outBuf, 0, outBuf.Length)
                Sleep(500)
        End Select

    End Sub

    Private Sub PrintBuffer(ByVal outbuf() As Byte, ByVal msg As String)
        Dim str_outbuf As String = "     ###        " + msg
        For Each bb1 As Byte In outbuf
            str_outbuf += " " & bb1.ToString()
        Next
        str_outbuf += String.Format("    ({0}) ", outbuf(2) * 256 + outbuf(3))
        Debug.WriteLine(str_outbuf)
    End Sub

    ''' <summary>
    ''' 发送指定的字符串，返回响应数据
    ''' </summary>
    ''' <param name="cmd"></param>
    ''' <returns></returns>
    ''' <remarks>
    ''' Added by hudan at 2008-03-05
    ''' </remarks>
    Public Function WriteCommand(ByVal cmd As String) As String
        Dim ret As String = String.Empty

        Select Case ConnectType
            Case 0, 1 '拨号,直连
                _sp.ReadExisting()
                _sp.Write(cmd & ControlChars.NewLine)
                System.Threading.Thread.Sleep(2000)
                ret = _sp.ReadExisting()
            Case 2 'TCP/IP
                _cs.ReceiveExisting()
                _cs.Send(cmd & ControlChars.NewLine)
                System.Threading.Thread.Sleep(2000)
                ret = _cs.ReceiveExisting()
        End Select

        Return ret
    End Function

    Public Function WriteCommand(ByVal cmd As String, ByVal length As Integer, ByVal timeout As Integer) As String
        Dim ret As String = String.Empty
        Dim count As Integer = timeout / 500

        Select Case ConnectType
            Case 0, 1 '拨号,直连
                _sp.ReadExisting()
                _sp.Write(cmd & ControlChars.NewLine)
                Do While count > 0 AndAlso _sp.BytesToRead < length
                    System.Threading.Thread.Sleep(500)
                    count -= 1
                Loop
                ret = _sp.ReadExisting()
            Case 2 'TCP/IP
                _cs.ReceiveExisting()
                _cs.Send(cmd & ControlChars.NewLine)
                Do While count > 0 AndAlso _cs.Available < length
                    System.Threading.Thread.Sleep(500)
                    count -= 1
                Loop
                ret = _cs.ReceiveExisting()
        End Select

        Return ret
    End Function

    Public Function WriteCommand(ByVal bytes() As Byte, ByVal length As Integer, ByVal timeout As Integer) As String
        Dim ret As String = String.Empty
        Dim count As Integer = timeout / 500

        Select Case ConnectType
            Case 0, 1 '拨号,直连
                _sp.ReadExisting()
                _sp.Write(bytes, 0, bytes.Length)
                'System.Threading.Thread.Sleep(2000)
                Do While count > 0 AndAlso _sp.BytesToRead < length
                    System.Threading.Thread.Sleep(500)
                    count -= 1
                Loop
                ret = _sp.ReadExisting()
            Case 2 'TCP/IP
                _cs.ReceiveExisting()
                _cs.Send(bytes)
                'System.Threading.Thread.Sleep(2000)
                Do While count > 0 AndAlso _cs.Available < length
                    System.Threading.Thread.Sleep(500)
                    count -= 1
                Loop
                ret = _cs.ReceiveExisting()
        End Select

        Return ret
    End Function


    ''' <summary>
    ''' 回复子控的查询
    ''' </summary>
    ''' <param name="cmd"></param>
    ''' <param name="reply"></param>
    ''' <param name="timeout"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function ReplyCommand(ByVal cmd As String, ByVal reply As String, ByVal timeout As Integer) As Boolean
        Dim str As String = ""
        Dim i As Integer
        While i < timeout AndAlso str.IndexOf(cmd) < 0
            i += 50
            Select Case ConnectType
                Case 0, 1 '拨号,直连
                    str &= _sp.ReadExisting()
                Case 2 'TCP/IP
                    str &= _cs.ReceiveExisting()
            End Select
            System.Threading.Thread.Sleep(50)
            Application.DoEvents()
        End While

        If str.IndexOf(cmd) >= 0 Then
            Select Case ConnectType
                Case 0, 1 '拨号,直连
                    _sp.Write(reply & ControlChars.NewLine)
                Case 2 'TCP/IP
                    _cs.Send(reply & ControlChars.NewLine)
            End Select
            Return True
        End If

        Return False
    End Function


    ''' <summary>
    ''' 读取指定子控的当前时间
    ''' </summary>
    ''' <param name="netID"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Function getCurrentTime(ByVal netID As Byte) As DateTime
        Dim dt As DateTime = DateTime.Now


        Dim buf() As Short
        '读子控时间
        buf = Me.Send4Short(netID, FunctionCode.WordReadonly, 0, 6)

        If buf IsNot Nothing Then
            Try
                dt = New DateTime(buf(0), buf(1), buf(2), buf(3), buf(4), buf(5))
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
        End If

        Return dt
    End Function

End Class

#Region "Socket Parameters Class"
Public Class SocketParametersClass
    Private _HeartbeatIdleTime As Integer
    Private _HeartbeatWaitTime As Integer
    Private _HeartbeatRep As Integer

    Public Property Heartbeat_IdleTime() As Integer
        Get
            Return _HeartbeatIdleTime
        End Get
        Set(ByVal value As Integer)
            _HeartbeatIdleTime = value
        End Set
    End Property

    Public Property Heartbeat_WaitTime() As Integer
        Get
            Return _HeartbeatWaitTime
        End Get
        Set(ByVal value As Integer)
            _HeartbeatWaitTime = value
        End Set
    End Property

    Public Property Heartbeat_Rep() As Integer
        Get
            Return _HeartbeatRep
        End Get
        Set(ByVal value As Integer)
            _HeartbeatRep = value
        End Set
    End Property
End Class
#End Region
